home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Script.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  31.4 KB  |  1,041 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19.  
  20. #include <crtdbg.h>
  21. #include <stdio.h>
  22.  
  23. #include <windows.h>
  24. #include <commdlg.h>
  25. #include <mmsystem.h>
  26.  
  27. #include "indeo_if.h"
  28.  
  29. #include "ScriptInterpreter.h"
  30. #include "ScriptValue.h"
  31. #include "ScriptError.h"
  32. #include "Error.h"
  33. #include "VideoSource.h"
  34.  
  35. #include "command.h"
  36. #include "dub.h"
  37. #include "gui.h"
  38. #include "prefs.h"
  39. #include "resource.h"
  40. #include "script.h"
  41.  
  42. extern DubOptions g_dubOpts;
  43. extern HWND g_hWnd;
  44.  
  45. extern const char g_szError[];
  46. extern bool g_fJobMode;
  47.  
  48. static HINSTANCE g_hInst, g_hInstSylia;
  49. static char g_szScriptFile[MAX_PATH];
  50. static IScriptInterpreter *(__stdcall *g_SyliaCreateInterpreter)();
  51.  
  52. extern void FreeCompressor(COMPVARS *pCompVars);
  53. static CScriptValue RootHandler(IScriptInterpreter *isi, char *szName, void *lpData);
  54.  
  55. bool InitScriptSystem() {
  56.     char buf[512];
  57.     long l;
  58.  
  59.     // Attempt to load SYLIA.DLL
  60.  
  61.     g_hInstSylia = LoadLibrary("Sylia.dll");
  62.  
  63.     if (GetLastError() == ERROR_DLL_NOT_FOUND || GetLastError() == ERROR_MOD_NOT_FOUND)
  64.         g_hInstSylia = LoadLibrary("i:\\projwin\\sylia\\release\\sylia.dll");
  65.  
  66.     if (!g_hInstSylia) {
  67.         strcpy(buf, "Cannot load Sylia scripting language (SYLIA.DLL):\n\n");
  68.         l = strlen(buf);
  69.         if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buf+l, (sizeof buf)-l, NULL))
  70.             MessageBox(NULL, buf, g_szError, MB_OK | MB_TASKMODAL);
  71.  
  72.         return false;
  73.     }
  74.  
  75.     if (!(g_SyliaCreateInterpreter = GETPROC_CREATESCRIPTINTERPRETER(g_hInstSylia))) {
  76.         MessageBox(NULL, "Error in Sylia.dll: No CreateScriptInterpreter()!", g_szError, MB_OK | MB_TASKMODAL | MB_TOPMOST);
  77.         FreeLibrary(g_hInstSylia);
  78.         g_hInstSylia = NULL;
  79.         return false;
  80.     }
  81.  
  82.     return true;
  83. }
  84.  
  85. void DeinitScriptSystem() {
  86.     if (g_hInstSylia) {
  87.         FreeLibrary(g_hInstSylia);
  88.  
  89.         g_hInstSylia = NULL;
  90.     }
  91. }
  92.  
  93.  
  94. void RunScript(char *name, void *hwnd) {
  95.     static char fileFilters[]=
  96.                 "All scripts (*.vcf,*.syl,*.jobs)\0"        "*.vcf;*.syl;*.jobs\0"
  97.                 "VirtualDub configuration file (*.vcf)\0"    "*.vcf\0"
  98.                 "Sylia script for VirtualDub (*.syl)\0"        "*.syl\0"
  99.                 "VirtualDub job queue (*.jobs)\0"            "*.jobs\0"
  100.                 "All Files (*.*)\0"                            "*.*\0"
  101.                 ;
  102.     OPENFILENAME ofn;
  103.     IScriptInterpreter *isi = NULL;
  104.     FILE *f = NULL;
  105.  
  106.     if (!name) {
  107.         ofn.lStructSize            = sizeof(OPENFILENAME);
  108.         ofn.hwndOwner            = (HWND)hwnd;
  109.         ofn.lpstrFilter            = fileFilters;
  110.         ofn.lpstrCustomFilter    = NULL;
  111.         ofn.nFilterIndex        = 1;
  112.         ofn.lpstrFile            = g_szScriptFile;
  113.         ofn.nMaxFile            = sizeof g_szScriptFile;
  114.         ofn.lpstrFileTitle        = NULL;
  115.         ofn.nMaxFileTitle        = 0;
  116.         ofn.lpstrInitialDir        = NULL;
  117.         ofn.lpstrTitle            = "Load configuration script";
  118.         ofn.Flags                = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING;
  119.         ofn.lpstrDefExt            = NULL;
  120.         ofn.hInstance            = g_hInst;
  121.  
  122.         if (!GetOpenFileName(&ofn)) return;
  123.  
  124.         name = g_szScriptFile;
  125.     }
  126.  
  127.     if (!InitScriptSystem())
  128.         return;
  129.  
  130.     try {
  131.         char lbuf[512];
  132.  
  133.         isi = g_SyliaCreateInterpreter();
  134.         if (!isi) throw MyError("Not enough memory to create script interpreter");
  135.  
  136.         isi->SetRootHandler(RootHandler, NULL);
  137.  
  138.         if (!(f=fopen(name, "r")))
  139.             throw MyError("Can't open script file");
  140.  
  141.         while(fgets(lbuf, sizeof lbuf, f)) {
  142.             isi->ExecuteLine(lbuf);
  143.         }
  144.  
  145.     } catch(CScriptError cse) {
  146.         MessageBox(NULL, isi->TranslateScriptError(cse), "Sylia script error", MB_OK | MB_TASKMODAL | MB_TOPMOST);
  147.     } catch(MyUserAbortError e) {
  148.         /* do nothing */
  149.     } catch(MyError e) {
  150.         e.post(NULL, g_szError);
  151.     }
  152.  
  153.     isi->Destroy();
  154.     if (f) fclose(f);
  155.  
  156.     DeinitScriptSystem();
  157.     RemakePositionSlider();
  158. }
  159.  
  160. void RunScriptMemory(char *mem) {
  161.     IScriptInterpreter *isi = NULL;
  162.  
  163.     if (!InitScriptSystem())
  164.         return;
  165.  
  166.     try {
  167.         char lbuf[512], *s=mem, *t;
  168.  
  169.         isi = g_SyliaCreateInterpreter();
  170.         if (!isi) throw MyError("Not enough memory to create script interpreter");
  171.  
  172.         isi->SetRootHandler(RootHandler, NULL);
  173.  
  174.         while(*s) {
  175.             t = s;
  176.             while(*t && *t!='\n') ++t;
  177.  
  178.             memcpy(lbuf, s, t-s);
  179.             lbuf[t-s]=0;
  180.             isi->ExecuteLine(lbuf);
  181.  
  182.             s = t;
  183.             if (*s=='\n') ++s;
  184.         }
  185.  
  186.     } catch(CScriptError cse) {
  187.         MessageBox(NULL, isi->TranslateScriptError(cse), "Sylia script error", MB_OK | MB_TASKMODAL);
  188.     } catch(MyUserAbortError e) {
  189.         isi->Destroy();
  190.         DeinitScriptSystem();
  191.         throw MyError("Aborted by user");
  192.     } catch(MyError e) {
  193.         isi->Destroy();
  194.         DeinitScriptSystem();
  195.  
  196.         throw;
  197. //        e.post(NULL, szError);
  198.     }
  199.  
  200.     isi->Destroy();
  201.  
  202.     DeinitScriptSystem();
  203. }
  204.  
  205. ///////////////////////////////////////////////////////////////////////////
  206. //
  207. //    General script-handler helper routines.
  208. //
  209. ///////////////////////////////////////////////////////////////////////////
  210.  
  211. static bool strfuzzycompare(const char *s, const char *t) {
  212.     char c,d;
  213.  
  214.     // Collapse spaces to one, convert symbols to _, and letters to uppercase...
  215.  
  216.     do {
  217.         c = *s++;
  218.  
  219.         if (isalpha(c)) c=toupper(c);
  220.         else if (isspace(c)) {
  221.             c = ' ';
  222.             while(*s && isspace(*s)) ++s;
  223.         } else if (c)
  224.             c = '_';
  225.  
  226.         d = *t++;
  227.  
  228.         if (isalpha(d)) d=toupper(d);
  229.         else if (isspace(d)) {
  230.             d = ' ';
  231.             while(*t && isspace(*t)) ++t;
  232.         } else if (d)
  233.             d = '_';
  234.  
  235.         if (c!=d) break;
  236.     } while(c && d);
  237.  
  238.     return c==d;
  239. }
  240.  
  241. static char base64[]=
  242.     "ABCDEFGHIJKLMNOP"
  243.     "QRSTUVWXYZabcdef"
  244.     "ghijklmnopqrstuv"
  245.     "wxyz0123456789+/"
  246.     "=";
  247.  
  248. void memunbase64(char *t, const char *s, long cnt) {
  249.  
  250.     char c1, c2, c3, c4, *ind, *limit = t+cnt;
  251.     long v;
  252.  
  253.     for(;;) {
  254.         while((c1=*s++) && !(ind = strchr(base64,c1)));
  255.         if (!c1) break;
  256.         c1 = (char)(ind-base64);
  257.  
  258.         while((c2=*s++) && !(ind = strchr(base64,c2)));
  259.         if (!c2) break;
  260.         c2 = (char)(ind-base64);
  261.  
  262.         while((c3=*s++) && !(ind = strchr(base64,c3)));
  263.         if (!c3) break;
  264.         c3 = (char)(ind-base64);
  265.  
  266.         while((c4=*s++) && !(ind = strchr(base64,c4)));
  267.         if (!c4) break;
  268.         c4 = (char)(ind-base64);
  269.  
  270.         // [c1,c4] valid -> 24 bits (3 bytes)
  271.         // [c1,c3] valid -> 18 bits (2 bytes)
  272.         // [c1,c2] valid -> 12 bits (1 byte)
  273.         // [c1] valid    ->  6 bits (0 bytes)
  274.  
  275.         v = ((c1 & 63)<<18) | ((c2 & 63)<<12) | ((c3 & 63)<<6) | (c4 & 63);
  276.  
  277.         if (c1!=64 && c2!=64) {
  278.             *t++ = (char)(v >> 16);
  279.  
  280.             if (t >= limit) return;
  281.  
  282.             if (c3!=64) {
  283.                 *t++ = (char)(v >> 8);
  284.                 if (t >= limit) return;
  285.                 if (c4!=64) {
  286.                     *t++ = (char)v;
  287.                     if (t >= limit) return;
  288.                     continue;
  289.                 }
  290.             }
  291.         }
  292.         break;
  293.     }
  294. }
  295.  
  296. void membase64(char *t, const char *s, long l) {
  297.  
  298.     unsigned char c1, c2, c3;
  299.  
  300.     while(l>0) {
  301.         c1 = (unsigned char)s[0];
  302.         if (l>1) {
  303.             c2 = (unsigned char)s[1];
  304.             if (l>2)
  305.                 c3 = (unsigned char)s[2];
  306.         }
  307.  
  308.         t[0] = base64[(c1 >> 2) & 0x3f];
  309.         if (l<1) {
  310.             t[1] = base64[(c1<<4)&0x3f];
  311.             t[2] = t[3] = '=';
  312.         } else {
  313.             t[1] = base64[((c1<<4)|(c2>>4))&0x3f];
  314.             if (l<2) {
  315.                 t[2] = base64[(c2<<2)&0x3f];
  316.                 t[3] = '=';
  317.             } else {
  318.                 t[2] = base64[((c2<<2) | (c3>>6))&0x3f];
  319.                 t[3] = base64[c3 & 0x3f];
  320.             }
  321.         }
  322.  
  323.         l-=3;
  324.         t+=4;
  325.         s+=3;
  326.     }
  327.     *t=0;
  328. }
  329.  
  330. ///////////////////////////////////////////////////////////////////////////
  331. //
  332. //    Object: VirtualDub.video.filters
  333. //
  334. ///////////////////////////////////////////////////////////////////////////
  335.  
  336. static void func_VDVFiltInst_Remove(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  337.     FilterInstance *fa = (FilterInstance *)lpVoid;
  338.  
  339.     fa->Remove();
  340.     fa->Destroy();
  341. }
  342.  
  343. static void func_VDVFiltInst_SetClipping(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  344.     FilterInstance *fa = (FilterInstance *)(FilterActivation *)lpVoid;
  345.  
  346.     fa->x1    = argv[0].asInt();
  347.     fa->y1    = argv[1].asInt();
  348.     fa->x2    = argv[2].asInt();
  349.     fa->y2    = argv[3].asInt();
  350. }
  351.  
  352. static int func_VDVFiltInst_GetClipping(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  353.     FilterInstance *fa = (FilterInstance *)(FilterActivation *)lpVoid;
  354.  
  355.     switch(argv[0].asInt()) {
  356.     case 0:    return fa->x1;
  357.     case 1: return fa->y1;
  358.     case 2: return fa->x2;
  359.     case 3: return fa->y2;
  360.     }
  361.  
  362.     return 0;
  363. }
  364.  
  365. static CScriptValue obj_VDVFiltInst_lookup(IScriptInterpreter *isi, CScriptObject *thisPtr, void *lpVoid, char *szName) {
  366.     FilterInstance *fa = (FilterInstance *)(FilterActivation *)lpVoid;
  367.  
  368.     if (fa->filter->script_obj)
  369.         return isi->LookupObjectMember(fa->filter->script_obj, lpVoid, szName);
  370.  
  371.     return CScriptValue();
  372. }
  373.  
  374. static ScriptFunctionDef obj_VDVFiltInst_functbl[]={
  375.     { (ScriptFunctionPtr)func_VDVFiltInst_Remove            , "Remove", "0" },
  376.     { (ScriptFunctionPtr)func_VDVFiltInst_SetClipping        , "SetClipping", "0iiii" },
  377.     { (ScriptFunctionPtr)func_VDVFiltInst_GetClipping        , "GetClipping", "0i" },
  378.     { NULL }
  379. };
  380.  
  381. static CScriptObject obj_VDVFiltInst={
  382.     obj_VDVFiltInst_lookup, obj_VDVFiltInst_functbl, NULL    
  383. };
  384.  
  385. ///////////////////
  386.  
  387. static CScriptValue obj_VDVFilters_instance(IScriptInterpreter *isi, void *, int index) {
  388.     FilterInstance *fa = (FilterInstance *)g_listFA.tail.next, *fa2;
  389.     CScriptValue t = CScriptValue(&obj_VDVFiltInst);
  390.  
  391.     while((fa2 = (FilterInstance *)fa->next) && index--)
  392.         fa = fa2;
  393.  
  394.     if (index!=-1 || !fa->next) EXT_SCRIPT_ERROR(VAR_NOT_FOUND);
  395.  
  396.     t.lpVoid = (FilterActivation *)fa;
  397.     return t;
  398. }
  399.  
  400. static void func_VDVFilters_Clear(IScriptInterpreter *, void *, CScriptValue *, int) {
  401.     FilterInstance *fa;
  402.  
  403.     while(fa = (FilterInstance *)g_listFA.RemoveHead()) {
  404.         fa->Destroy();
  405.     }
  406. }
  407.  
  408. static int func_VDVFilters_Add(IScriptInterpreter *isi, CScriptObject *, CScriptValue *argv, int argc) {
  409.     FilterDefinition *fm = filter_list;
  410.  
  411.     while(fm) {
  412.         if (strfuzzycompare(fm->name, *argv[0].asString())) {
  413.             FilterInstance *fa = new FilterInstance(fm);
  414.  
  415.             if (!fa) EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  416.  
  417.             fa->x1 = fa->y1 = fa->x2 = fa->y2 = 0;
  418.  
  419.             g_listFA.AddHead(fa);
  420.  
  421.             {
  422.                 int count = 0;
  423.  
  424.                 FilterInstance *fa = (FilterInstance *)g_listFA.tail.next, *fa2;
  425.  
  426.                 while(fa2 = (FilterInstance *)fa->next) {
  427.                     fa = fa2;
  428.                     ++count;
  429.                 }
  430.  
  431.                 return count-1;
  432.             }
  433.         }
  434.  
  435.         fm = fm->next;
  436.     }
  437.  
  438.     throw MyError("Cannot add filter '%s': no such filter loaded", *argv[0].asString());
  439. }
  440.  
  441. static CScriptValue obj_VDVFilters_lookup(IScriptInterpreter *isi, CScriptObject *thisPtr, void *lpVoid, char *szName) {
  442.     if (!strcmp(szName, "instance"))
  443.         return CScriptValue(thisPtr, &obj_VDVFilters_instance);
  444.  
  445.     EXT_SCRIPT_ERROR(MEMBER_NOT_FOUND);
  446. }
  447.  
  448. static ScriptFunctionDef obj_VDVFilters_functbl[]={
  449.     { (ScriptFunctionPtr)func_VDVFilters_Clear            , "Clear", "0" },
  450.     { (ScriptFunctionPtr)func_VDVFilters_Add            , "Add", "is", },
  451.     { NULL }
  452. };
  453.  
  454. static CScriptObject obj_VDVFilters={
  455.     obj_VDVFilters_lookup, obj_VDVFilters_functbl, NULL    
  456. };
  457.  
  458. ///////////////////////////////////////////////////////////////////////////
  459. //
  460. //    Object: VirtualDub.video
  461. //
  462. ///////////////////////////////////////////////////////////////////////////
  463.  
  464. static int func_VDVideo_GetDepth(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  465.     return arglist[0].asInt() ? g_dubOpts.video.outputDepth : g_dubOpts.video.inputDepth;
  466. }
  467.  
  468. static void func_VDVideo_SetDepth(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  469.     int new_depth1, new_depth2;
  470.  
  471.     switch(arglist[0].asInt()) {
  472.     case 16:    new_depth1 = 0; break;
  473.     case 24:    new_depth1 = 1; break;
  474.     case 32:    new_depth1 = 2; break;
  475.     default:
  476.         return;
  477.     }
  478.  
  479.     switch(arglist[1].asInt()) {
  480.     case 16:    new_depth2 = 0; break;
  481.     case 24:    new_depth2 = 1; break;
  482.     case 32:    new_depth2 = 2; break;
  483.     default:
  484.         return;
  485.     }
  486.  
  487.     g_dubOpts.video.inputDepth = new_depth1;
  488.     g_dubOpts.video.outputDepth = new_depth2;
  489. }
  490.  
  491. static int func_VDVideo_GetMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  492.     return g_dubOpts.video.mode;
  493. }
  494.  
  495. static void func_VDVideo_SetMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  496.     int new_mode = arglist[0].asInt();
  497.  
  498.     if (new_mode>=0 && new_mode<4)
  499.         g_dubOpts.video.mode = new_mode;
  500. }
  501.  
  502. static int func_VDVideo_GetFrameRate(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  503.     switch(arglist[0].asInt()) {
  504.     case 0: return g_dubOpts.video.frameRateDecimation;
  505.     case 1: return g_dubOpts.video.frameRateNewMicroSecs;
  506.     case 2: return g_dubOpts.video.fInvTelecine;
  507.     }
  508.     return 0;
  509. }
  510.  
  511. static void func_VDVideo_SetFrameRate(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  512.     g_dubOpts.video.frameRateNewMicroSecs = arglist[0].asInt();
  513.     g_dubOpts.video.frameRateDecimation = arglist[1].asInt();
  514.  
  515.     if (arg_count > 2) {
  516.         if (arglist[2].asInt()) {
  517.             g_dubOpts.video.fInvTelecine = true;
  518.             g_dubOpts.video.fIVTCMode = false;
  519.             g_dubOpts.video.nIVTCOffset = -1;
  520.             g_dubOpts.video.fIVTCPolarity = false;
  521.         } else {
  522.             g_dubOpts.video.fInvTelecine = false;
  523.         }
  524.     }
  525. }
  526.  
  527. static int func_VDVideo_GetRange(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  528.     return arglist[0].asInt() ? g_dubOpts.video.lEndOffsetMS : g_dubOpts.video.lStartOffsetMS;
  529. }
  530.  
  531. static void func_VDVideo_SetRange(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  532.     SetSelectionStart(arglist[0].asInt());
  533.     SetSelectionEnd(arglist[1].asInt());
  534. }
  535.  
  536. static int func_VDVideo_GetCompression(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  537.     if (!g_Vcompression.dwFlags & ICMF_COMPVARS_VALID)
  538.         return 0;
  539.  
  540.     switch(arglist[0].asInt()) {
  541.     case 0:    return (int)g_Vcompression.fccHandler;
  542.     case 1: return g_Vcompression.lKey;
  543.     case 2: return g_Vcompression.lQ;
  544.     case 3: return g_Vcompression.lDataRate;
  545.     }
  546.  
  547.     return 0;
  548. }
  549.  
  550. static void func_VDVideo_SetCompression(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  551. //    ICCompressorFree(&g_Vcompression);
  552.     FreeCompressor(&g_Vcompression);
  553.  
  554.     memset(&g_Vcompression, 0, sizeof(COMPVARS));
  555.  
  556.     if (!arg_count) return;
  557.  
  558.     g_Vcompression.cbSize    = sizeof(COMPVARS);
  559.     g_Vcompression.dwFlags |= ICMF_COMPVARS_VALID;
  560.  
  561.     g_Vcompression.fccType        = ICTYPE_VIDEO;
  562.  
  563.     if (arglist[0].isString()) {
  564.         g_Vcompression.fccHandler    = 0x20202020;
  565.         memcpy(&g_Vcompression.fccHandler, *arglist[0].asString(), min(4,strlen(*arglist[0].asString())));
  566.     } else
  567.         g_Vcompression.fccHandler    = arglist[0].asInt();
  568.  
  569.     g_Vcompression.lKey            = arglist[1].asInt();
  570.     g_Vcompression.lQ            = arglist[2].asInt();
  571.     g_Vcompression.lDataRate    = arglist[3].asInt();
  572.     g_Vcompression.hic            = ICOpen(g_Vcompression.fccType, g_Vcompression.fccHandler, ICMODE_COMPRESS);
  573. }
  574.  
  575. static void func_VDVideo_SetCompData(IScriptInterpreter *isi, CScriptObject *, CScriptValue *arglist, int arg_count) {
  576.     void *mem;
  577.     long l = ((strlen(*arglist[1].asString())+3)/4)*3;
  578.  
  579.     if (!(g_Vcompression.dwFlags & ICMF_COMPVARS_VALID))
  580.         return;
  581.  
  582.     if (arglist[0].asInt() > l) return;
  583.  
  584.     l = arglist[0].asInt();
  585.  
  586.     if (!(mem = allocmem(l)))
  587.         EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  588.  
  589.     _CrtCheckMemory();
  590.     memunbase64((char *)mem, *arglist[1].asString(), l);
  591.     _CrtCheckMemory();
  592.  
  593.     ICSetState(g_Vcompression.hic, mem, l);
  594.  
  595.     freemem(mem);
  596. }
  597.  
  598. static void func_VDVideo_EnableIndeoQC(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  599.     R4_ENC_SEQ_DATA r4enc;
  600.  
  601.     if (!(g_Vcompression.dwFlags & ICMF_COMPVARS_VALID))
  602.         return;
  603.  
  604.     if ((g_Vcompression.fccHandler & 0xFFFF) != 'VI')
  605.         return;
  606.  
  607.     r4enc.dwSize            = sizeof(R4_ENC_SEQ_DATA);
  608.     r4enc.dwFourCC            = g_Vcompression.fccHandler;
  609.     r4enc.dwVersion            = SPECIFIC_INTERFACE_VERSION;
  610.     r4enc.mtType            = MT_ENCODE_SEQ_VALUE;
  611.     r4enc.oeEnvironment        = OE_32;
  612.     r4enc.dwFlags            = ENCSEQ_VALID | ENCSEQ_QUICK_COMPRESS;
  613.     r4enc.fQuickCompress    = !!arglist[0].asInt();
  614.  
  615.     ICSetState(g_Vcompression.hic, &r4enc, sizeof r4enc);
  616. }
  617.  
  618. static void func_VDVideo_SetIVTC(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  619.     R4_ENC_SEQ_DATA r4enc;
  620.  
  621.     g_dubOpts.video.fInvTelecine = !!arglist[0].asInt();
  622.     g_dubOpts.video.fIVTCMode = !!arglist[1].asInt();
  623.     g_dubOpts.video.nIVTCOffset = arglist[2].asInt();
  624.     if (g_dubOpts.video.nIVTCOffset >= 0)
  625.         g_dubOpts.video.nIVTCOffset %= 5;
  626.     g_dubOpts.video.fIVTCPolarity = !!arglist[3].asInt();
  627. }
  628.  
  629. static ScriptFunctionDef obj_VDVideo_functbl[]={
  630.     { (ScriptFunctionPtr)func_VDVideo_GetDepth            , "GetDepth", "ii" },
  631.     { (ScriptFunctionPtr)func_VDVideo_SetDepth            , "SetDepth", "0ii" },
  632.     { (ScriptFunctionPtr)func_VDVideo_GetMode            , "GetMode", "i" },
  633.     { (ScriptFunctionPtr)func_VDVideo_SetMode            , "SetMode", "0i" },
  634.     { (ScriptFunctionPtr)func_VDVideo_GetFrameRate        , "GetFrameRate", "ii" },
  635.     { (ScriptFunctionPtr)func_VDVideo_SetFrameRate        , "SetFrameRate", "0ii" },
  636.     { (ScriptFunctionPtr)func_VDVideo_SetFrameRate        , NULL, "0iii" },
  637.     { (ScriptFunctionPtr)func_VDVideo_GetRange            , "GetRange", "ii" },
  638.     { (ScriptFunctionPtr)func_VDVideo_SetRange            , "SetRange", "0ii" },
  639.     { (ScriptFunctionPtr)func_VDVideo_GetCompression    , "GetCompression"    , "0ii" },
  640.     { (ScriptFunctionPtr)func_VDVideo_SetCompression    , "SetCompression"    , "0siii" },
  641.     { (ScriptFunctionPtr)func_VDVideo_SetCompression    , NULL                , "0iiii" },
  642.     { (ScriptFunctionPtr)func_VDVideo_SetCompression    , NULL                , "0" },
  643.     { (ScriptFunctionPtr)func_VDVideo_SetCompData        , "SetCompData", "0is" },
  644.     { (ScriptFunctionPtr)func_VDVideo_EnableIndeoQC        , "EnableIndeoQC", "0i" },
  645.     { (ScriptFunctionPtr)func_VDVideo_SetIVTC            , "SetIVTC", "0iiii" },
  646.     { NULL }
  647. };
  648.  
  649. static ScriptObjectDef obj_VDVideo_objtbl[]={
  650.     { "filters", &obj_VDVFilters },
  651.     { NULL }
  652. };
  653.  
  654. static CScriptValue obj_VirtualDub_video_lookup(IScriptInterpreter *isi, CScriptObject *obj, void *lpVoid, char *szName) {
  655.     if (!strcmp(szName, "width"))
  656.         return CScriptValue(inputVideoAVI ? inputVideoAVI->getImageFormat()->biWidth : 0);
  657.     else if (!strcmp(szName, "height"))
  658.         return CScriptValue(inputVideoAVI ? inputVideoAVI->getImageFormat()->biHeight : 0);
  659.  
  660.     EXT_SCRIPT_ERROR(MEMBER_NOT_FOUND);
  661. }
  662.  
  663. static CScriptObject obj_VDVideo={
  664.     obj_VirtualDub_video_lookup, obj_VDVideo_functbl, obj_VDVideo_objtbl
  665. };
  666.  
  667. ///////////////////////////////////////////////////////////////////////////
  668. //
  669. //    Object: VirtualDub.audio
  670. //
  671. ///////////////////////////////////////////////////////////////////////////
  672.  
  673. static int func_VDAudio_GetMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  674.     return g_dubOpts.audio.mode;
  675. }
  676.  
  677. static void func_VDAudio_SetMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  678.     int new_mode = arglist[0].asInt();
  679.  
  680.     if (new_mode>=0 && new_mode<2)
  681.         g_dubOpts.audio.mode = new_mode;
  682. }
  683.  
  684. static int func_VDAudio_GetInterleave(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  685.     switch(arglist[0].asInt()) {
  686.     case 0:    return g_dubOpts.audio.enabled;
  687.     case 1:    return g_dubOpts.audio.preload;
  688.     case 2:    return g_dubOpts.audio.interval;
  689.     case 3:    return g_dubOpts.audio.is_ms;
  690.     case 4: return g_dubOpts.audio.offset;
  691.     }
  692.  
  693.     return 0;
  694. }
  695.  
  696. static void func_VDAudio_SetInterleave(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  697.     g_dubOpts.audio.enabled        = !!arglist[0].asInt();
  698.     g_dubOpts.audio.preload        = arglist[1].asInt();
  699.     g_dubOpts.audio.interval    = arglist[2].asInt();
  700.     g_dubOpts.audio.is_ms        = !!arglist[3].asInt();
  701.     g_dubOpts.audio.offset        = arglist[4].asInt();
  702. }
  703.  
  704. static int func_VDAudio_GetClipMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  705.     switch(arglist[0].asInt()) {
  706.     case 0:        return g_dubOpts.audio.fStartAudio;
  707.     case 1:        return g_dubOpts.audio.fEndAudio;
  708.     }
  709.  
  710.     return 0;
  711. }
  712.  
  713. static void func_VDAudio_SetClipMode(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  714.     g_dubOpts.audio.fStartAudio    = !!arglist[0].asInt();
  715.     g_dubOpts.audio.fEndAudio    = !!arglist[1].asInt();
  716. }
  717.  
  718. static int func_VDAudio_GetConversion(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  719.     switch(arglist[0].asInt()) {
  720.     case 0:        return g_dubOpts.audio.new_rate;
  721.     case 1:        return g_dubOpts.audio.newPrecision;
  722.     case 2:        return g_dubOpts.audio.newChannels;
  723.     }
  724.  
  725.     return 0;
  726. }
  727.  
  728. static void func_VDAudio_SetConversion(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  729.     g_dubOpts.audio.new_rate        = arglist[0].asInt();
  730.     g_dubOpts.audio.newPrecision    = arglist[1].asInt();
  731.     g_dubOpts.audio.newChannels        = arglist[2].asInt();
  732.  
  733.     if (arg_count >= 5) {
  734.         g_dubOpts.audio.integral_rate    = !!arglist[3].asInt();
  735.         g_dubOpts.audio.fHighQuality    = !!arglist[4].asInt();
  736.     }
  737. }
  738.  
  739. static void func_VDAudio_SetSource(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  740.     if (arglist[0].isInt())
  741.         audioInputMode = !!arglist[0].asInt();
  742.     else {
  743.         OpenWAV(*arglist[0].asString());
  744.         audioInputMode = AUDIOIN_WAVE;
  745.     }
  746. }
  747.  
  748. static void func_VDAudio_SetCompressionPCM(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  749.     PCMWAVEFORMAT *pwf = (PCMWAVEFORMAT *)allocmem(sizeof(PCMWAVEFORMAT));
  750.  
  751.     if (!pwf) EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  752.  
  753.     pwf->wf.wFormatTag            = WAVE_FORMAT_PCM;
  754.     pwf->wf.nSamplesPerSec        = arglist[0].asInt();
  755.     pwf->wf.nChannels            = arglist[1].asInt();
  756.     pwf->   wBitsPerSample        = arglist[2].asInt();
  757.     pwf->wf.nBlockAlign        = (pwf->wBitsPerSample/8) * pwf->wf.nChannels;
  758.     pwf->wf.nAvgBytesPerSec    = pwf->wf.nSamplesPerSec * pwf->wf.nBlockAlign;
  759.     g_ACompressionFormatSize = sizeof(PCMWAVEFORMAT);
  760.     freemem(g_ACompressionFormat);
  761.     g_ACompressionFormat = (WAVEFORMATEX *)pwf;
  762. }
  763.  
  764. // VirtualDub.audio.SetCompression();
  765. // VirtualDub.audio.SetCompression(tag, sampling_rate, channels, bits, bytes/sec, blockalign);
  766. // VirtualDub.audio.SetCompression(tag, sampling_rate, channels, bits, bytes/sec, blockalign, exdatalen, exdata);
  767.  
  768. static void func_VDAudio_SetCompression(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  769.     WAVEFORMATEX *wfex;
  770.     long ex_data=0;
  771.  
  772.     if (!arg_count) {
  773.         freemem(g_ACompressionFormat);
  774.         g_ACompressionFormat = NULL;
  775.         return;
  776.     }
  777.  
  778.     if (arg_count > 6)
  779.         ex_data = arglist[6].asInt();
  780.  
  781.     if (!(wfex = (WAVEFORMATEX *)allocmem(sizeof(WAVEFORMATEX) + ex_data)))
  782.         EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  783.  
  784.     wfex->wFormatTag        = arglist[0].asInt();
  785.     wfex->nSamplesPerSec    = arglist[1].asInt();
  786.     wfex->nChannels            = arglist[2].asInt();
  787.     wfex->wBitsPerSample    = arglist[3].asInt();
  788.     wfex->nAvgBytesPerSec    = arglist[4].asInt();
  789.     wfex->nBlockAlign        = arglist[5].asInt();
  790.     wfex->cbSize            = (WORD)ex_data;
  791.  
  792.     if (arg_count > 6) {
  793.         long l = ((strlen(*arglist[7].asString())+3)/4)*3;
  794.  
  795.         if (ex_data > l) {
  796.             freemem(wfex);
  797.             return;
  798.         }
  799.  
  800.         memunbase64((char *)(wfex+1), *arglist[7].asString(), ex_data);
  801.     }
  802.  
  803.     _CrtCheckMemory();
  804.  
  805.     if (g_ACompressionFormat)
  806.         freemem(g_ACompressionFormat);
  807.  
  808.     g_ACompressionFormat = wfex;
  809.  
  810.     if (wfex->wFormatTag == WAVE_FORMAT_PCM)
  811.         g_ACompressionFormatSize = sizeof(PCMWAVEFORMAT);
  812.     else
  813.         g_ACompressionFormatSize = sizeof(WAVEFORMATEX)+ex_data;
  814.  
  815.     _CrtCheckMemory();
  816. }
  817.  
  818. static void func_VDAudio_SetVolume(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  819.     if (arg_count)
  820.         g_dubOpts.audio.volume = arglist[0].asInt();        
  821.     else
  822.         g_dubOpts.audio.volume = 0;
  823. }
  824.  
  825. static int func_VDAudio_GetVolume(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  826.     return g_dubOpts.audio.volume;
  827. }
  828.  
  829. static ScriptFunctionDef obj_VDAudio_functbl[]={
  830.     { (ScriptFunctionPtr)func_VDAudio_GetMode            , "GetMode"                , "i"        },
  831.     { (ScriptFunctionPtr)func_VDAudio_SetMode            , "SetMode"                , "0i"        },
  832.     { (ScriptFunctionPtr)func_VDAudio_GetInterleave        , "GetInterleave"        , "ii"        },
  833.     { (ScriptFunctionPtr)func_VDAudio_SetInterleave        , "SetInterleave"        , "0iiiii"    },
  834.     { (ScriptFunctionPtr)func_VDAudio_GetClipMode        , "GetClipMode"            , "ii"        },
  835.     { (ScriptFunctionPtr)func_VDAudio_SetClipMode        , "SetClipMode"            , "0ii"        },
  836.     { (ScriptFunctionPtr)func_VDAudio_GetConversion        , "GetConversion"        , "ii"        },
  837.     { (ScriptFunctionPtr)func_VDAudio_SetConversion        , "SetConversion"        , "0iii"    },
  838.     { (ScriptFunctionPtr)func_VDAudio_SetConversion        , NULL                    , "0iiiii"    },
  839.     { (ScriptFunctionPtr)func_VDAudio_SetSource            , "SetSource"            , "0i"        },
  840.     { (ScriptFunctionPtr)func_VDAudio_SetSource            , NULL                    , "0s"        },
  841.     { (ScriptFunctionPtr)func_VDAudio_SetCompressionPCM    , "SetCompressionPCM"    , "0iii"    },
  842.     { (ScriptFunctionPtr)func_VDAudio_SetCompression    , "SetCompression"        , "0"        },
  843.     { (ScriptFunctionPtr)func_VDAudio_SetCompression    , NULL                    , "0iiiiii" },
  844.     { (ScriptFunctionPtr)func_VDAudio_SetCompression    , NULL                    , "0iiiiiiis" },
  845.     { (ScriptFunctionPtr)func_VDAudio_SetVolume            , "SetVolume"            , "0" },
  846.     { (ScriptFunctionPtr)func_VDAudio_SetVolume            , NULL                    , "0i" },
  847.     { (ScriptFunctionPtr)func_VDAudio_GetVolume            , "GetVolume"            , "i" },
  848.     { NULL }
  849. };
  850.  
  851. static CScriptObject obj_VDAudio={
  852.     NULL, obj_VDAudio_functbl
  853. };
  854.  
  855. ///////////////////////////////////////////////////////////////////////////
  856. //
  857. //    Object: VirtualDub.subset
  858. //
  859. ///////////////////////////////////////////////////////////////////////////
  860.  
  861. static void func_VDSubset_Delete(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  862.     if (inputSubset) {
  863.         delete inputSubset;
  864.         inputSubset = NULL;
  865.     }
  866. }
  867.  
  868. static void func_VDSubset_Clear(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  869.     if (inputSubset) {
  870.         delete inputSubset;
  871.         inputSubset = NULL;
  872.     }
  873.  
  874.     if (!(inputSubset = new FrameSubset()))
  875.         EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  876. }
  877.  
  878. static void func_VDSubset_AddFrame(IScriptInterpreter *isi, void *, CScriptValue *arglist, int arg_count) {
  879.     if (!inputSubset && !(inputSubset = new FrameSubset()))
  880.         EXT_SCRIPT_ERROR(OUT_OF_MEMORY);
  881.  
  882.     inputSubset->addRange(arglist[0].asInt(), arglist[1].asInt());
  883. }
  884.  
  885. static ScriptFunctionDef obj_VDSubset_functbl[]={
  886.     { (ScriptFunctionPtr)func_VDSubset_Delete            , "Delete"                , "0"        },
  887.     { (ScriptFunctionPtr)func_VDSubset_Clear            , "Clear"                , "0"        },
  888.     { (ScriptFunctionPtr)func_VDSubset_AddFrame            , "AddFrame"            , "0ii"        },
  889.  
  890.     { NULL }
  891. };
  892.  
  893. static CScriptObject obj_VDSubset={
  894.     NULL, obj_VDSubset_functbl
  895. };
  896.  
  897.  
  898. ///////////////////////////////////////////////////////////////////////////
  899. //
  900. //    Object: VirtualDub
  901. //
  902. ///////////////////////////////////////////////////////////////////////////
  903.  
  904. extern void CloseAVI();
  905. extern void PreviewAVI(HWND, DubOptions *, int iPriority=0, bool fProp=false);
  906.  
  907. static void func_VirtualDub_SetStatus(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  908.     guiSetStatus("%s", 255, *arglist[0].asString());
  909. }
  910.  
  911. static void func_VirtualDub_Open(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  912.     if (arg_count > 3) {
  913.         long l = ((strlen(*arglist[3].asString())+3)/4)*3;
  914.         char buf[64];
  915.  
  916.         memunbase64(buf, *arglist[3].asString(), l);
  917.  
  918.         OpenAVI(*arglist[0].asString(), arglist[1].asInt(), !!arglist[2].asInt(), true, false, buf);
  919.     } else
  920.         OpenAVI(*arglist[0].asString(), arglist[1].asInt(), !!arglist[2].asInt(), true, false);
  921. }
  922.  
  923. static void func_VirtualDub_Append(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  924.     AppendAVI(*arglist[0].asString());
  925. }
  926.  
  927. static void func_VirtualDub_Close(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  928.     CloseAVI();
  929. }
  930.  
  931. static void func_VirtualDub_Preview(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  932.     PreviewAVI(g_hWnd, NULL, g_prefs.main.iPreviewPriority,true);
  933. }
  934.  
  935. static void func_VirtualDub_SaveAVI(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  936.     if (g_fJobMode) {
  937.         DubOptions opts(g_dubOpts);
  938.  
  939.         opts.fShowStatus            = false;
  940.         opts.fMoveSlider            = true;
  941.         opts.video.fShowInputFrame    = false;
  942.         opts.video.fShowOutputFrame    = false;
  943.         opts.video.fShowDecompressedFrame    = false;
  944.  
  945.         SaveAVI(*arglist[0].asString(), true, &opts, false);
  946.     } else
  947.         SaveAVI(*arglist[0].asString(), true, NULL, false);
  948. }
  949.  
  950. static void func_VirtualDub_SaveCompatibleAVI(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  951.     if (g_fJobMode) {
  952.         DubOptions opts(g_dubOpts);
  953.  
  954.         opts.fShowStatus            = false;
  955.         opts.fMoveSlider            = true;
  956.         opts.video.fShowInputFrame    = false;
  957.         opts.video.fShowOutputFrame    = false;
  958.         opts.video.fShowDecompressedFrame    = false;
  959.  
  960.         SaveAVI(*arglist[0].asString(), true, &opts, true);
  961.     } else
  962.         SaveAVI(*arglist[0].asString(), true, NULL, true);
  963. }
  964.  
  965. static void func_VirtualDub_SaveSegmentedAVI(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  966.     if (g_fJobMode) {
  967.         DubOptions opts(g_dubOpts);
  968.  
  969.         opts.fShowStatus            = false;
  970.         opts.fMoveSlider            = true;
  971.         opts.video.fShowInputFrame    = false;
  972.         opts.video.fShowOutputFrame    = false;
  973.         opts.video.fShowDecompressedFrame    = false;
  974.  
  975.         SaveSegmentedAVI(*arglist[0].asString(), true, &opts, arglist[1].asInt(), arglist[2].asInt());
  976.     } else
  977.         SaveSegmentedAVI(*arglist[0].asString(), true, NULL, arglist[1].asInt(), arglist[2].asInt());
  978. }
  979.  
  980. static void func_VirtualDub_SaveWAV(IScriptInterpreter *, CScriptObject *, CScriptValue *arglist, int arg_count) {
  981.     SaveWAV(*arglist[0].asString());
  982. }
  983.  
  984. extern "C" unsigned long version_num;
  985.  
  986. static CScriptValue obj_VirtualDub_lookup(IScriptInterpreter *isi, CScriptObject *obj, void *lpVoid, char *szName) {
  987.     if (!strcmp(szName, "version")) {
  988.         char buf1[256], buf[256], **handle;
  989.  
  990.         LoadString(g_hInst, IDS_TITLE_INITIAL, buf, sizeof buf);
  991.  
  992.         wsprintf(buf1, buf, version_num,
  993. #ifdef _DEBUG
  994.             "debug"
  995. #else
  996.             "release"
  997. #endif
  998.             );
  999.  
  1000.         handle = isi->AllocTempString(strlen(buf1));
  1001.  
  1002.         strcpy(*handle, buf1);
  1003.  
  1004.         return CScriptValue(handle);
  1005.     } else if (!strcmp(szName, "video"))
  1006.         return &obj_VDVideo;
  1007.     else if (!strcmp(szName, "audio"))
  1008.         return &obj_VDAudio;
  1009.     else if (!strcmp(szName, "subset"))
  1010.         return &obj_VDSubset;
  1011.  
  1012.     EXT_SCRIPT_ERROR(MEMBER_NOT_FOUND);
  1013. }
  1014.  
  1015. static ScriptFunctionDef obj_VirtualDub_functbl[]={
  1016.     { (ScriptFunctionPtr)func_VirtualDub_SetStatus,            "SetStatus",            "0s" },
  1017.     { (ScriptFunctionPtr)func_VirtualDub_Open,                "Open",                    "0sii" },
  1018.     { (ScriptFunctionPtr)func_VirtualDub_Open,                NULL,                    "0siis" },
  1019.     { (ScriptFunctionPtr)func_VirtualDub_Append,            "Append",                "0s" },
  1020.     { (ScriptFunctionPtr)func_VirtualDub_Open,                NULL,                    "0siis" },
  1021.     { (ScriptFunctionPtr)func_VirtualDub_Close,                "Close",                "0" },
  1022.     { (ScriptFunctionPtr)func_VirtualDub_Preview,            "Preview",                "0" },
  1023.     { (ScriptFunctionPtr)func_VirtualDub_SaveAVI,            "SaveAVI",                "0s" },
  1024.     { (ScriptFunctionPtr)func_VirtualDub_SaveCompatibleAVI, "SaveCompatibleAVI",    "0s" },
  1025.     { (ScriptFunctionPtr)func_VirtualDub_SaveSegmentedAVI,    "SaveSegmentedAVI",        "0sii" },
  1026.     { (ScriptFunctionPtr)func_VirtualDub_SaveWAV,            "SaveWAV",                "0s" },
  1027.     { NULL }
  1028. };
  1029.  
  1030. static CScriptObject obj_VirtualDub={
  1031.     &obj_VirtualDub_lookup, obj_VirtualDub_functbl
  1032. };
  1033.  
  1034. static CScriptValue RootHandler(IScriptInterpreter *isi, char *szName, void *lpData) {
  1035.     if (!strcmp(szName, "VirtualDub"))
  1036.         return &obj_VirtualDub;
  1037.  
  1038.     EXT_SCRIPT_ERROR(VAR_NOT_FOUND);
  1039. }
  1040.  
  1041.